﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

// qt headers
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QJsonObject>
#include <QFileDialog>
#include <QPainter>
#include <QJsonArray>
#include <QJsonDocument>

//  gcmp headers
#include "IJournalCommandData.h"
#include "JournalUtils.h"
#include "CommandParameters.h"

// custom headers
#include "UploadWindow.h"
#include "ICategory.h"

#include "SelectingFileItem.h"
#include "GbmpNew.h"
#include "OwnerPtr.h"
#include "GmepFilePathSettings.h"
#include "IGmepCategoryInfoUtils.h"
#include "IFamilyFileThumbnail.h"
#include "ComponentData.h"
#include "ComponentSqlUtils.h"
#include "GbmpFileSystem.h"
#include "FilePath.h"
#include "ModelViewEnums.h"
#include "IGmepProjectSettingComponent.h"
#include "FileUtility.h"
#include "IParameterDefinitionLibrary.h"
#include "IParameterDefinition.h"
#include "ParameterType.h"
#include "IUiDocumentViewManager.h"
#include "IUiView.h"
#include "IUiDocument.h"
#include <chrono>
#include "json/value.h"
#include "ComponentCommonUtils.h"
#include "BnufBulletin.h"
#include "UnitUniIdentities.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "GCSGacZipUtils.h"
#include "pugixml.h"
#include "GmepBuiltInParameterDefinitions.h"
#include "GmepUnitUtils.h"
#include "GmepStandardCode.h"
#include <Iphlpapi.h>
#pragma comment(lib,"Iphlpapi.lib")
#include "IGmepCategoryInfo.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 


using namespace gcmp;

namespace
{
    IDocument* GetCurrentDocument()
    {
        IUiView* pUIView = IUiDocumentViewManager::Get()->GetCurrentUiView();
        if (!pUIView)
            return nullptr;

        IUiDocument* pUIDoc = pUIView->GetUiDocument();
        DBG_WARN_UNLESS(pUIDoc != nullptr, L"IUiDocument为空", L"GMEP", L"2024-01-30");

        IDocument* pDocument = pUIDoc->GetDbDocument();
        DBG_WARN_UNLESS(pDocument, L"IDocument为空", L"GMEP", L"2024-01-30");
        return pDocument;
    }

    std::wstring RemoveBracket(std::wstring& strGuidwithBracket)
    {
        size_t pos = strGuidwithBracket.find('{');
        if (pos >= 0)
            strGuidwithBracket = strGuidwithBracket.erase(pos, 1);
        pos = std::wstring::npos;
        pos = strGuidwithBracket.find('}');
        if (pos >= 0)
            strGuidwithBracket = strGuidwithBracket.erase(pos, 1);

        return strGuidwithBracket;
    }

    long long GetIp(const std::string& ip22)
    {
        std::vector<std::string> splitStrings = StringUtil::SplitString(ip22, ".");
        DBG_WARN_AND_RETURN_UNLESS(splitStrings.size() == 4, -1, L"GetIp出错", L"GMEP", L"2024-01-30");
        long long a = (std::stoll(splitStrings[0]) << 24) +
            (std::stoll(splitStrings[1]) << 16) +
            (std::stoll(splitStrings[2]) << 8) +
            (std::stoll(splitStrings[3]));
        return a;
    }

    long long GetWorkerId()
    {
        long long id = -1;
        PIP_ADAPTER_INFO pAdapterInfo;
        PIP_ADAPTER_INFO pAdapter = NULL;
        DWORD errValue = 0;
        ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
        if (!pAdapterInfo)
            return id;
        // Make an initial call to GetAdaptersInfo to get the necessary size into the ulOutBufLen variable. -- 摘自微软官网
        if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) 
        {
            free(pAdapterInfo);
            pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
            if (pAdapterInfo == NULL) 
            {
                return id;
            }
        }
        if ((errValue = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
        {
            pAdapter = pAdapterInfo;
            if (pAdapter)
            {
                std::string s = pAdapter->IpAddressList.IpAddress.String;
                id = 255L & GetIp(s);
            }
        }
        if (pAdapterInfo)
            free(pAdapterInfo);
        return id;
    }

    long long GetCurrentTimeMillis()
    {
        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    }

    long long UntilNextMillis(long long lastTimestamp)
    {
        long long timestamp = 0;
        for (timestamp = GetCurrentTimeMillis(); timestamp <= lastTimestamp; timestamp = GetCurrentTimeMillis())
        {
        }

        return timestamp;
    }

    static long long sequence = 0L;
    static long long lastTimestamp = 0L;
    static long long workerId = -1L;
    std::wstring GenerateComponentId()
    {
        std::wstring componnetId;
        long long timestamp = GetCurrentTimeMillis();
        if (lastTimestamp == timestamp) {
            sequence = sequence + 1L & 31L;
            if (sequence == 0L) {
                timestamp = UntilNextMillis(lastTimestamp);
            }
        }
        else {
            sequence = 0L;
        }
        if (timestamp < lastTimestamp)
        {
            DBG_WARN(L"timestamp < lastTimestamp", L"GMEP", L"2024-01-30");
            return componnetId;
        }

        lastTimestamp = timestamp;
        if (workerId == -1L)
        {
            workerId = GetWorkerId();
            DBG_WARN_AND_RETURN_UNLESS(workerId != -1, L"", L"GetWorkerId失败", L"GMEP", L"2024-01-30");
        }
        long long nextId = ((timestamp - 1361753741828L) << 13) | (workerId << 5) | sequence;
        componnetId = std::to_wstring(nextId);
        return componnetId;
    }
}

namespace gmepgcs 
{
    UploadWindow::UploadWindow() 
    {
    };

    UploadWindow::~UploadWindow()
    {

    }

    UploadWindow *UploadWindow::s_pInstance = nullptr;
    UploadWindow * UploadWindow::Get()
    {
        if (!UploadWindow::s_pInstance)
        {
            UploadWindow::s_pInstance = NEW_AS_QT(UploadWindow);
        }
        return UploadWindow::s_pInstance;
    }
   
    bool UploadWindow::AddTaskLocal(const std::wstring &projectId, const QStringList pathList,bool bIsConnect, std::wstring* strError)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(strError, L"strError为空", L"GMEP", L"2024-01-30");
        std::vector<gcmp::OwnerPtr<SelectingFileItem>> vecSelectedFile;
        for (auto &file : pathList)
        {
            gcmp::OwnerPtr<SelectingFileItem> opSelectingFileItem = NEW_AS_OWNER_PTR(SelectingFileItem, file);
            if (opSelectingFileItem->Remark().length() > 0)
            {
                std::wstring sMsg = opSelectingFileItem->Remark().toStdWString();
                BnufBulletin::SingleShot(sMsg, BnufBulletin::BulletinIcon::Error);
                continue;
            }

            vecSelectedFile.emplace_back(TransferOwnership(opSelectingFileItem));
        }

        if ((int)vecSelectedFile.size() == 0)
        {
            *strError = GBMP_TR(L"未选择文件！");
            return false;
        }
        bool bResult = AddSelectedFile(projectId, vecSelectedFile, bIsConnect,strError);
        if (!bResult && strError)
        {
            //*strError += L"以上文件数据库中已经存在，导入出错！";
        }
        return bResult;
    }

    std::wstring UploadWindow::CreateFamilyThumbnail(const std::wstring& gacFile) const
    {
        FilePath filePath(FileSystem::GetPurePath(gacFile));
        std::wstring sOutPath = FilePath::Combine(FileSystem::GetTempDirPath(), filePath.GetFileNameWithoutExtension() + L"_3D.png");

        std::wstring sThumbnailPath = L"";
        OwnerPtr<IFamilyFileThumbnail> opFamilyThumbnail = IFamilyFileThumbnail::Create(gacFile);
        DBG_WARN_AND_RETURN_UNLESS(nullptr != opFamilyThumbnail, sThumbnailPath, L"opFamilyThumbnail为空", L"GMEP", L"2024-01-30");

        std::vector<std::wstring> vecFamilyTypeName = opFamilyThumbnail->GetFamilyTypeNames();
        DBG_WARN_AND_RETURN_UNLESS((int)vecFamilyTypeName.size() > 0, sThumbnailPath, L"GetFamilyTypeNames出错", L"GMEP", L"2024-01-30");

        FileThumbnailExportOption options;
        options.Width = 256;
        options.Height = 256;
        options.FamilyTypeName = vecFamilyTypeName.at(0);
        options.OutputFilePath = sOutPath;
        options.CameraDirection = -Vector3d(sin(Constants::MATH_PI / 180 * 135), cos(Constants::MATH_PI / 180 * 135), 1.0) * 1000;
        options.CameraDirection.Normalize();
        ModelViewDisplayOptions displayOptions;
        {
            displayOptions.HasLight = true;
            displayOptions.HasMaterial = true;
            displayOptions.ShowElementEdges = true;
        }
        options.DisplayOptions = displayOptions;
        options.DisplayMode = ModelViewDisplayMode::Solid;
        options.DisplayDetailLevel = ModelViewDetailLevel::Fine;
        bool ret = opFamilyThumbnail->CreateThumbnail(options);
        DBG_WARN_AND_RETURN_UNLESS(ret, sThumbnailPath, L"CreateThumbnail出错", L"GMEP", L"2024-01-30");
        sThumbnailPath = sOutPath;

        return sThumbnailPath;
    }

    int UploadWindow::CheckFileIsExistOnLocal(const std::wstring &projectId, QStringList& pathList)
    {
        std::vector<gcmp::OwnerPtr<SelectingFileItem>> vecSelectedFile;
        for (auto &file : pathList)
        {
            gcmp::OwnerPtr<SelectingFileItem> opSelectingFileItem = NEW_AS_OWNER_PTR(SelectingFileItem, file);
            if (opSelectingFileItem->Remark().length() > 0)
            {
                continue;
            }

            vecSelectedFile.emplace_back(TransferOwnership(opSelectingFileItem));
        }

        int nCount = 0;
        const std::wstring dbFilePath = GmepFilePathSettings::GetTemporaryProjectDBFilePath(projectId);
        gmep::IGmepCategoryInfoUtils* pUtil = gmep::GmepCategoryInfoUtilsHandler::Get().GetUtils();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pUtil, L"pUtil为空", L"GMEP", L"2024-01-30");
        FOR_EACH(file, vecSelectedFile)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(nullptr != file, L"file为空", L"GMEP", L"2024-01-30");
            //
            std::wstring sCategoryGuid = file->GetCategoryGuid();
            DBG_WARN_AND_CONTINUE_UNLESS((int)sCategoryGuid.size() > 3, L"GetCategoryGuid出错", L"GMEP", L"2024-01-30");
            sCategoryGuid = sCategoryGuid.substr(1, sCategoryGuid.length() - 2);
            std::transform(sCategoryGuid.begin(), sCategoryGuid.end(), sCategoryGuid.begin(), toupper);

            std::wstring standardCode;
            bool ret = pUtil->GetStandardCodeByCategoryGuid(sCategoryGuid, standardCode);
            //20230730 禁止添加卫浴gac到项目构件管理
            if (ret && CODE_BATHROOM_EQUIPMENT == standardCode)
                ret = false;
            if (!ret)
            {
                int iPos = pathList.indexOf(file->FilePath());
                if (iPos >= 0)
                {
                    pathList.removeAt(iPos);
                }
                
                std::wstring sMsg = StringUtil::FormatWString(GBMP_TR(L"构件:”%s“机电不能识别。"), file->FileName().toStdWString().c_str());
                BnufBulletin::SingleShot(sMsg, BnufBulletin::BulletinIcon::Error);
                continue;
            }
            //DBG_WARN_AND_RETURN_FALSE_UNLESS(ret, L"GetStandardCodeByCategoryGuid出错", L"GMEP", L"2024-01-30");
            gcmp::OwnerPtr<gmep::IGmepCategoryInfo> retCategory = nullptr;
            ret = pUtil->GetCategoryInfo(sCategoryGuid, retCategory);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(ret, L"GetCategoryInfo出错", L"GMEP", L"2024-01-30");

            std::wstring tableName = retCategory->GetMappedId();
            FilePath filePath(FileSystem::GetPurePath(file->FilePath().toStdWString()));
            std::wstring sFileName = filePath.GetFileNameWithoutExtension();

            GmepComponent comp;
            comp.id = L"-1";
            comp.name = sFileName;

            if (ComponentSqlUtils::SearchComponentNameIsExistFromDB(dbFilePath, retCategory.get(), comp))
            {
                nCount++;
            }
        }

        return nCount;
    }

    bool UploadWindow::AddSelectedFile(const std::wstring &projectId, const std::vector<gcmp::OwnerPtr<SelectingFileItem>>& vecSelectedFile, bool bIsConnect, std::wstring* strError) const
    {
        bool bResult = true;
        const std::wstring dbFilePath = GmepFilePathSettings::GetTemporaryProjectDBFilePath(projectId);
        const std::wstring product3DPath = GmepFilePathSettings::GetTemporaryProjectProduct3DFolderPath(projectId);
        gmep::IGmepCategoryInfoUtils* pUtil = gmep::GmepCategoryInfoUtilsHandler::Get().GetUtils();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pUtil, L"pUtil为空", L"GMEP", L"2024-01-30");

        FOR_EACH(file, vecSelectedFile)
        {
            DBG_WARN_AND_RETURN_FALSE_UNLESS(nullptr != file, L"file为空", L"GMEP", L"2024-01-30");
            std::wstring sThumbnailPath = CreateFamilyThumbnail(file->FilePath().toStdWString());
            if ((sThumbnailPath).size() == 0)
            {
                continue;
            }
           
            std::wstring sCategoryGuid = file->GetCategoryGuid();
            DBG_WARN_AND_RETURN_FALSE_UNLESS((int)sCategoryGuid.size() > 3, L"GetCategoryGuid出错", L"GMEP", L"2024-01-30");
            sCategoryGuid = sCategoryGuid.substr(1, sCategoryGuid.length() - 2);
            std::transform(sCategoryGuid.begin(), sCategoryGuid.end(), sCategoryGuid.begin(), toupper);

            std::wstring standardCode;
            bool ret = pUtil->GetStandardCodeByCategoryGuid(sCategoryGuid, standardCode);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(ret, L"GetStandardCodeByCategoryGuid出错", L"GMEP", L"2024-01-30");
            gcmp::OwnerPtr<gmep::IGmepCategoryInfo> retCategory = nullptr;
            ret = pUtil->GetCategoryInfo(sCategoryGuid, retCategory);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(ret, L"GetCategoryInfo出错", L"GMEP", L"2024-01-30");

            std::wstring tableName = retCategory->GetMappedId();
            FilePath thumbnailPath(FileSystem::GetPurePath(sThumbnailPath));
            std::wstring sNewThumbnailPath = FilePath::Combine(product3DPath, tableName, thumbnailPath.GetFileName());

            FilePath filePath(FileSystem::GetPurePath(file->FilePath().toStdWString()));
            std::wstring sFileName = filePath.GetFileNameWithoutExtension();
            std::wstring sNewGacPath = FilePath::Combine(product3DPath, tableName, filePath.GetFileName());

            std::vector<GmepComponent> vecComp;
            GmepComponent comp;
            comp.categoryCode = standardCode;
            comp.id = GenerateComponentId();
            comp.publicComponentId = L"0";// 本地导入的gac 公共库id 为0
            comp.name = sFileName;

            comp.thumbnailFilePath = sNewThumbnailPath;
            comp.familyFilePath = sNewGacPath;
            comp.mergedFamilyFilePath = L"";
            comp.thumbnail2DFileId = L"";  // 主图例的id

            comp.family2DInfo.id = L"";
            comp.family2DInfo.name = L"";
            comp.family2DInfo.thumbnailUrl = L"";
            comp.family2DFrontInfo.id = L"";
            comp.family2DFrontInfo.name = L"";
            comp.family2DFrontInfo.thumbnailUrl = L"";
            comp.family2DLeftInfo.id = L"";
            comp.family2DLeftInfo.name = L"";
            comp.family2DLeftInfo.thumbnailUrl = L"";
            comp.family2DElecInfo.id = L"";
            comp.family2DElecInfo.name = L"";
            comp.family2DElecInfo.thumbnailUrl = L"";

            comp.iSource = 1;
            comp.dirtyFlag = GmepComponentDirtyFlag::LocalAddedFromPublic;
            comp.iTimeStamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();

            //判断是否已经存在
            if (ComponentSqlUtils::SearchComponentNameIsExistFromDB(dbFilePath, retCategory.get(), comp) && strError)
            {
                if (bIsConnect)
                {
                    continue;
                }
                std::wstring returnName = L"";
                ComponentSqlUtils::SearchComponentNamelikeFromDB(dbFilePath, retCategory.get(), comp, returnName);
                std::wstring::size_type nPos = sNewGacPath.find(sFileName);
                if (nPos != std::wstring::npos)
                {
                    WCHAR pBuf[1] = { L'\0' };
                    sNewGacPath.replace(nPos, sFileName.length(), pBuf, 0);
                    sNewGacPath.insert(nPos, returnName);
                }
                nPos = sNewThumbnailPath.find(sFileName);
                if (nPos != std::wstring::npos)
                {
                    WCHAR pBuf[1] = { L'\0' };
                    sNewThumbnailPath.replace(nPos, sFileName.length(), pBuf, 0);
                    sNewThumbnailPath.insert(nPos, returnName);
                }
                comp.name = returnName;
                comp.thumbnailFilePath = sNewThumbnailPath;
                comp.familyFilePath = sNewGacPath;
            }
            
            bool copySucc = CopySingleFile(file->FilePath().toStdWString(), sNewGacPath);
            if (!copySucc)
                continue;
            if (!GetComponentType(sNewGacPath, retCategory.get(), comp))
            {
                FileSystem::RemoveFile(sNewGacPath);
                continue;
            }
            vecComp.emplace_back(comp);
         
            CopySingleFile(sThumbnailPath, sNewThumbnailPath);
            FileSystem::RemoveFile(sThumbnailPath);

            bool bRet = ComponentSqlUtils::SaveAddedComponentsOfOneCategory(dbFilePath, retCategory.get(), vecComp);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(bRet, L"SaveAddedComponentsOfOneCategory出错", L"GMEP", L"2024-01-30");
            bResult &= bRet;
        }
      
        return bResult;
    }
        
    bool UploadWindow::CopySingleFile(const std::wstring& srcFilePath, const std::wstring& targetFilePath) const
    {
        if (!gcmp::FileInfo(srcFilePath).Exists())
            return false;
        if (gcmp::FileInfo(targetFilePath).Exists())
            return true;

        bool bSucc = false;
        int nPos = static_cast<int>(targetFilePath.find_last_of(L"\\"));
        std::wstring wstrDirectory = targetFilePath.substr(0, nPos);

        if (!gcmp::FileInfo(wstrDirectory).Exists())
            FileUtility::CreateDirectories(wstrDirectory, false);

        return FileUtility::CopyFileW(srcFilePath, targetFilePath);
    }

    bool UploadWindow::GetComponentType(const std::wstring& gacFile, const gmep::IGmepCategoryInfo* pCategory, GmepComponent& comp) const
    {
        std::wstring sParametersXml = StringUtil::ToWString(gmepgcs::GacZipUtils::GetFamilyParametersXml(gacFile));

        OwnerPtr<IFamilyFile> pIFamilyFile = IFamilyFile::Create(gacFile);
        DBG_WARN_AND_RETURN_UNLESS(nullptr != pIFamilyFile, false, L"pIFamilyFile为空", L"GMEP", L"2024-01-30");
        comp.geometryParamDefinitions = CreateGeometryParamDefinitionsJson(pIFamilyFile.get(), sParametersXml, pCategory, comp);

        /*20230730临时接受构件坞带规格gac*/
        RemoveStandardNodesFromXML(gacFile, sParametersXml);
        //
        return true;
    }

    bool UploadWindow::GetPropertyInfo(const gmep::IGmepCategoryInfo* pCategory,
        const std::map<std::wstring, std::tuple<std::wstring, std::wstring>>& mapProperty,
        GmepComponentType& componentType) const
    {
        
        DBG_WARN_AND_RETURN_UNLESS(nullptr != pCategory, false, L"pCategory为空", L"GMEP", L"2024-01-30");
        
        std::wstring sStandardCode = pCategory->GetStandardCode();
        std::map<std::wstring, const gmep::IGmepPropertyInfo*> propertyInfoList = pCategory->GetPropertyInfoList();

        for (auto itr = propertyInfoList.begin(); itr != propertyInfoList.end(); itr++)
        {
            DBG_WARN_AND_RETURN_FALSE_UNLESS(itr->second, L"itr->second为空", L"GMEP", L"2024-01-30");
            // 实例参数和扩展参数都要跳过
            bool bInstanceParam = itr->second->IsInstanceParam();
            bool bBasicParam = itr->second->IsBasicProperty();
            if (bInstanceParam || !bBasicParam)
                continue;

            std::wstring sUnit = L"";
            std::wstring sUnitCode = L"";
            
            std::wstring sStandardCode = itr->second->GetStandardCode();
            auto propertyItr = mapProperty.find(sStandardCode);
            if (propertyItr != mapProperty.end())
            {
                std::tie(sUnit, sUnitCode) = propertyItr->second;
            }

            std::wstring sName = itr->second->GetName();

            GmepComponentParameterValue newParamValue;
            newParamValue.isDriveParameter = false;
            newParamValue.name = sName;
            newParamValue.code = sStandardCode;
            newParamValue.value = L"";
            newParamValue.unit = sUnit;
            newParamValue.unitCode = sUnitCode;
            newParamValue.storageType = (int)itr->second->GetStorageType();

            // 若已经存在了则不必添加
            if (!sStandardCode.empty())
            {
                if(componentType.paramValues.find(sStandardCode) == componentType.paramValues.end())
                    componentType.paramValues.emplace(sStandardCode, newParamValue);
            }
            else
            {
                if (componentType.paramValues.find(sName) == componentType.paramValues.end())
                    componentType.paramValues.emplace(sName, newParamValue);
            }
        }
        
        return true;
    }


    std::wstring UploadWindow::CreateGeometryParamDefinitionsJson(gcmp::IFamilyFile* pIFamilyFile, const std::wstring& sParametersXml, const gmep::IGmepCategoryInfo* pCategory, GmepComponent& comp) const
    {
        std::wstring sJson;
        DBG_WARN_AND_RETURN_UNLESS(nullptr != pIFamilyFile, sJson, L"pIFamilyFile为空", L"GMEP", L"2024-01-30");

        pugi::xml_document xmlDoc;
        pugi::xml_parse_result result = xmlDoc.load(sParametersXml.c_str());
        DBG_WARN_AND_RETURN_UNLESS(pugi::status_ok == result.status, sJson, L"加载XML文件失败", L"GMEP", L"2024-01-30");

        DBG_WARN_AND_RETURN_UNLESS(pCategory != nullptr, sJson, L"pCategory为空", L"GMEP", L"2024-01-30");
        /*20230730临时接受构件坞带规格gac*/
        std::wstring categoryStandardCode = pCategory->GetStandardCode();
        std::map<std::wstring, const gmep::IGmepPropertyInfo*> propertyInfoList = pCategory->GetPropertyInfoList();
        std::map<std::wstring, std::tuple<std::wstring, std::wstring>> mapProperty = ComponentCommonUtils::GetCategoryPropertyMap(categoryStandardCode);

        QJsonArray arrParamDef;

        FamilyParametersInformation familyParametersInformation;
        pIFamilyFile->GetFamilyParametersInformation(familyParametersInformation);
        bool hasAddedGeomDefinition = false;
        FOR_EACH(familyTypeInfo, familyParametersInformation.FamilyTypeInformation)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(nullptr != familyTypeInfo,  L"familyTypeInfo为空", L"GMEP", L"2024-01-30");
            std::wstring sTypeName = familyTypeInfo->FamilyTypeName;

            GmepComponentType newCompType;
            newCompType.typeName = sTypeName;
            std::wstring sGuid = familyTypeInfo->FamilyTypeUid.GetGuidString();
            DBG_WARN_AND_CONTINUE_UNLESS(sGuid.size() >= 0,  L"TypeUid为空", L"GMEP", L"2024-01-30");
            newCompType.typeId = RemoveBracket(sGuid);

            
            std::vector<OwnerPtr<IParameter>>& vecParameter = familyTypeInfo->Parameters;
            FOR_EACH(parameterItem, vecParameter)
            {
                DBG_WARN_AND_CONTINUE_UNLESS(nullptr != parameterItem,  L"parameterItem为空", L"GMEP", L"2024-01-30");
                UniIdentity uid = parameterItem->GetParameterDefinitionUid();
                DBG_WARN_AND_CONTINUE_UNLESS(nullptr != familyParametersInformation.ParameterDefinitionLibrary,  L"ParameterDefinitionLibrary为空", L"GMEP", L"2024-01-30");
                const gcmp::IParameterDefinition* pParameterDefinition = familyParametersInformation.ParameterDefinitionLibrary->GetParameterDefinitionByUid(uid);
                DBG_WARN_AND_CONTINUE_UNLESS(nullptr != pParameterDefinition,  L"pParameterDefinition为空", L"GMEP", L"2024-01-30");

                std::wstring sName = parameterItem->GetName();
                // 几何参数
                const std::wstring sCode = pParameterDefinition->GetStandardCode();
                UniIdentity paraTypeId = pParameterDefinition->GetParameterTypeId();
                if (sCode.empty() && (paraTypeId == PARAMETER_TYPE(Length) || paraTypeId == PARAMETER_TYPE(Angle) || paraTypeId == PARAMETER_TYPE(YesNo)
                    || paraTypeId == PARAMETER_TYPE(Number) || paraTypeId == PARAMETER_TYPE(Float)
                    || PARAMETER_UID(InstancePlacementTypeBuiltInParamter) == uid || PARAMETER_UID(DevicePartType) == uid))
                {
                    ParameterStorageType storageType = pParameterDefinition->GetStorageType();

                    std::wstring GroupName = pParameterDefinition->GetGroupName();
                    std::wstring Id = pParameterDefinition->GetUid().GetGuidString();
                    bool IsDrivingParameter = parameterItem->IsDriveParameter();

                    std::wstring sStandardType = L"";
                    std::wstring sParameterType = L"";
                    std::wstring sType = L"";
                    std::wstring sFormula = L"";
                    std::map<std::wstring, std::wstring> mapValue;
                    GetParameterInfo(&xmlDoc, sName, sStandardType, sParameterType, sType, sFormula, mapValue);

                    bool IsEssential = false;
                    if (StrICmp(sStandardType.c_str(), L"StandardEssential") == 0)
                        IsEssential = true;

                    bool IsGeometry = parameterItem->IsGeometricParameter();
                    bool IsInstance = !parameterItem->IsTypeParameter();
                    bool bOutputParameter = parameterItem->IsOutputParameter();
                    bool isVisible = parameterItem->IsUserVisible();
                    bool IsModifiable = parameterItem->IsModifiable();

                    bool IsStandard = true;
                    if (StrICmp(sStandardType.c_str(), L"NotStandard") == 0)
                        IsStandard = false;

                    UniIdentity parameterTypeId = pParameterDefinition->GetParameterTypeId();
                    std::wstring ParameterDisplayType = GetParameterDisplayType(parameterTypeId);

                    UniIdentity unitTypeId = gmep::GmepUnitUtils::GetGmepUnitType(pParameterDefinition);
                    std::wstring UnitSymbol = GetUnitType(unitTypeId);
                    std::wstring UnitCode = L"";
                    std::wstring sUnit = L"";
                    if (StrICmp(UnitSymbol.c_str(), L"Length") == 0)
                    {
                        sUnit = L"mm";
                    }
                    else if (StrICmp(UnitSymbol.c_str(), L"Angle") == 0)
                    {
                        sUnit = L"°";
                    }

                    const IParameterValueStorage* pParameterValueStorage = parameterItem->GetParameterValueStorage();
                    DBG_WARN_AND_CONTINUE_UNLESS(nullptr != pParameterValueStorage, L"pParameterValueStorage为空", L"GMEP", L"2024-01-30");
                    gcmp::ParameterStorageType eParameterStorageType = pParameterValueStorage->GetParameterStorageType();
                    std::wstring ValueType = GetValueType(eParameterStorageType);
                    if ((int)mapValue.size() > 0)
                    {
                        ValueType = L"Enum";
                    }

                    bool IsBuiltIn = false;
                    if (StrICmp(sType.c_str(), L"builtin") == 0)
                        IsBuiltIn = true;

                    bool IsShared = false;
                    if (StrICmp(sType.c_str(), L"shared") == 0)
                        IsShared = true;

                    bool IsFromFile = true;

                    bool bDriveParameter = parameterItem->IsDriveParameter();

                    //
                    GmepComponentParameterValue newParamValue;
                    newParamValue.isDriveParameter = bDriveParameter;
                    newParamValue.name = sName;
                    newParamValue.code = L"";

                    switch (storageType)
                    {
                    case ParameterStorageType::Double:
                        newParamValue.value = StringUtil::ToWString(parameterItem->GetValueAsDouble(), 3);
                        break;

                    case ParameterStorageType::Int:
                        newParamValue.value = StringUtil::ToWString(parameterItem->GetValueAsInt());
                        break;

                    case ParameterStorageType::Bool:
                        if (parameterItem->GetValueAsBool())
                            newParamValue.value = GBMP_TR(L"1");
                        else
                            newParamValue.value = GBMP_TR(L"0");
                        break;
                    }

                    if (!IsBuiltIn)
                    {
                        bool bEditable = ComponentCommonUtils::IsValueEditable(IsGeometry, bDriveParameter, bOutputParameter);
                        newParamValue.isDriveParameter = bEditable && (storageType == ParameterStorageType::Double || storageType == ParameterStorageType::Int || storageType == ParameterStorageType::Bool);
                    }

                    newParamValue.unit = sUnit;
                    newParamValue.unitCode = UnitCode;
                    newParamValue.storageType = (int)storageType;
                    newCompType.paramValues.emplace(sName, newParamValue);

                    // definition 只需要加一遍
                    if (!hasAddedGeomDefinition)
                    {
                        QJsonObject parameterObject;
                        parameterObject["code"] = QString::fromStdWString(sCode);
                        parameterObject["description"] = "";
                        parameterObject["formula"] = QString::fromStdWString(sFormula);
                        parameterObject["groupName"] = QString::fromStdWString(GroupName);
                        parameterObject["guid"] = "";
                        parameterObject["id"] = QString::fromStdWString(Id);
                        parameterObject["isBuildIn"] = IsBuiltIn;
                        parameterObject["isDriveParameter"] = bDriveParameter;
                        parameterObject["isEssential"] = IsEssential;
                        parameterObject["isFromFile"] = IsFromFile;
                        parameterObject["isGeometry"] = IsGeometry;
                        parameterObject["isInstance"] = IsInstance;
                        parameterObject["isModifiable"] = IsModifiable; // 20221230
                        parameterObject["isOutputParameter"] = bOutputParameter;
                        parameterObject["isShared"] = IsShared;
                        parameterObject["isStandard"] = IsStandard;
                        parameterObject["isUserVisible"] = isVisible;// 20221230
                        parameterObject["name"] = QString::fromStdWString(sName);
                        parameterObject["paramType"] = QString::fromStdWString(sParameterType);
                        parameterObject["parameterDisplayType"] = QString::fromStdWString(ParameterDisplayType);
                        parameterObject["parameterType"] = QString::fromStdWString(GetParameterStorageType(storageType));
                        parameterObject["unit"] = QString::fromStdWString(sUnit);
                        parameterObject["unitCode"] = QString::fromStdWString(UnitCode);
                        parameterObject["valueType"] = QString::fromStdWString(ValueType);

                        if ((int)mapValue.size() > 0)
                        {
                            QJsonObject valuesObject;
                            FOR_EACH(valueItem, mapValue)
                            {
                                valuesObject[QString::fromStdWString(valueItem.first)] = QString::fromStdWString(valueItem.second);
                            }
                            parameterObject["values"] = valuesObject;
                        }
                        else
                        {
                            parameterObject["values"] = QJsonValue::Null;
                        }

                        arrParamDef.append(parameterObject);
                        
                    }
                }
                else if(!sCode.empty())
                {
                    /*20230730临时接受构件坞带规格gac*/
                    // 业务参数,若有
                    ParameterStorageType gacStorageType = pParameterDefinition->GetStorageType();
                    std::wstring GroupName = pParameterDefinition->GetGroupName();
                    std::wstring Id = pParameterDefinition->GetUid().GetGuidString();
                    std::wstring IdWithoutRacket = RemoveBracket(Id);
                    const gmep::IGmepPropertyInfo* pProperty = nullptr;
                    std::transform(IdWithoutRacket.begin(), IdWithoutRacket.end(), IdWithoutRacket.begin(), toupper);
                    std::map<std::wstring, const gmep::IGmepPropertyInfo*>::const_iterator iter =  propertyInfoList.find(IdWithoutRacket);
                    if (iter != propertyInfoList.end()) // 应是业务属性
                       pProperty = iter->second;
                    else
                    {
                        std::transform(IdWithoutRacket.begin(), IdWithoutRacket.end(), IdWithoutRacket.begin(), tolower);
                        iter = propertyInfoList.find(IdWithoutRacket);
                        if (iter != propertyInfoList.end())
                            pProperty = iter->second;
                    }
                    //DBG_WARN_AND_CONTINUE_UNLESS(pProperty != nullptr , sName+L"不是业务属性", L"GMEP", L"2024-01-30");
                    if (pProperty == nullptr) // 应是业务属性
                    {
                        FYI(sName + L"不是业务属性");
                        continue;
                    }
                    bool bInstanceParam = pProperty->IsInstanceParam();
                    if (bInstanceParam)
                        continue;

                    short istorageType = pProperty->GetStorageType();

                    std::wstring sUnit = L"";
                    std::wstring sUnitCode = L"";
                    auto propertyItr = mapProperty.find(sCode);
                    if (propertyItr != mapProperty.end())
                    {
                        std::tie(sUnit, sUnitCode) = propertyItr->second;
                    }

                    GmepComponentParameterValue newParamValue;
                    newParamValue.isDriveParameter = false;
                    newParamValue.name = sName;
                    newParamValue.code = sCode;
                    //newParamValue.value = L"";
                    newParamValue.unit = sUnit;
                    newParamValue.unitCode = sUnitCode;
                    newParamValue.storageType = istorageType;

                    std::wstring sStandardType = L"";
                    std::wstring sParameterType = L"";
                    std::wstring sType = L"";
                    std::wstring sFormula = L"";
                    std::map<std::wstring, std::wstring> mapValue;
                    GetParameterInfo(&xmlDoc, sName, sStandardType, sParameterType, sType, sFormula, mapValue);

                    // gac里的storage type
                    switch (gacStorageType)
                    {
                    case ParameterStorageType::Double:
                        newParamValue.value = StringUtil::ToWString(parameterItem->GetValueAsDouble(), 3);
                        break;

                    case ParameterStorageType::Int:
                          newParamValue.value = StringUtil::ToWString(parameterItem->GetValueAsInt());
                        break;

                    case ParameterStorageType::Bool:
                        if (parameterItem->GetValueAsBool())
                            newParamValue.value = L"1";
                        else
                            newParamValue.value = L"0";
                        break;
                    case ParameterStorageType::String:
                        {
                            std::wstring strValue = parameterItem->GetValueAsString();
                            if (ParameterStorageType::Int == (ParameterStorageType)istorageType)
                            {
                                // 枚举的情况，需要将标准码转为int
                                std::map<std::wstring, int> enumIntMap = pProperty->GetEnumValueStandardCodeList();
                                if (enumIntMap.find(strValue) != enumIntMap.end())
                                {
                                    int iValue = enumIntMap[strValue];
                                    newParamValue.value = StringUtil::ToWString(iValue);
                                }
                            }
                            else
                                newParamValue.value = strValue;
                        }
                        break;
                    default:
                        break;
                    }

                    // 若已经存在了则不必添加
                    if (!sCode.empty())
                    {
                        if (newCompType.paramValues.find(sCode) == newCompType.paramValues.end())
                            newCompType.paramValues.emplace(sCode, newParamValue);
                    }
                    else
                    {
                        if (newCompType.paramValues.find(sName) == newCompType.paramValues.end())
                            newCompType.paramValues.emplace(sName, newParamValue);
                    }
                }
            }
            // 若gac里没有的业务参数需要补全，添加业务参数
            GetPropertyInfo(pCategory, mapProperty, newCompType);

            comp.types.emplace_back(newCompType);
            hasAddedGeomDefinition = true;
        }

        QJsonDocument jdoc;
        jdoc.setArray(arrParamDef);
        QByteArray jsonBytes = jdoc.toJson(QJsonDocument::Compact);
        return QString::fromUtf8(jsonBytes).toStdWString();
    }

    bool UploadWindow::GetParameterInfo(pugi::xml_document* xmlDoc, const std::wstring& sName, std::wstring& sStandardType, std::wstring& sParameterType, std::wstring& sType, std::wstring& sFormula, std::map<std::wstring, std::wstring>& mapValue) const
    {
        DBG_WARN_AND_RETURN_UNLESS(nullptr != xmlDoc, false, L"xmlDoc为空", L"GMEP", L"2024-01-30");
        pugi::xpath_node paramsPath = xmlDoc->select_single_node(L"/Root/FamilyParameterDefinitions");
        if (nullptr == paramsPath)
            return false;

        pugi::xml_node paramsNode = paramsPath.node();
        if (nullptr == paramsNode)
            return false;

        for (pugi::xml_node paramNode = paramsNode.first_child(); !paramNode.empty(); paramNode = paramNode.next_sibling())
        {
            sType = paramNode.attribute(L"type").value();
            
            pugi::xpath_node namePath = paramNode.select_single_node(L"Name");
            if (nullptr == namePath)
                continue;
            pugi::xml_node nameNode = namePath.node();
            if (nullptr == nameNode)
                continue;
            if (StrICmp(nameNode.text().as_string(), sName.c_str()) == 0)
            {
                pugi::xpath_node standardTypePath = paramNode.select_single_node(L"StandardType");
                if (nullptr != standardTypePath)
                {
                    pugi::xml_node standardTypeNode = standardTypePath.node();
                    sStandardType = standardTypeNode.text().as_string();
                }

                pugi::xpath_node paramTypePath = paramNode.select_single_node(L"ParamType");
                if (nullptr != paramTypePath)
                {
                    pugi::xml_node paramTypeNode = paramTypePath.node();
                    sParameterType = paramTypeNode.text().as_string();
                }

                pugi::xpath_node formulaPath = paramNode.select_single_node(L"Formula");
                if (nullptr != formulaPath)
                {
                    pugi::xml_node formulaNode = formulaPath.node();
                    sFormula = formulaNode.text().as_string();
                }

                pugi::xpath_node enumListPath = paramNode.select_single_node(L"EnumList");
                if (nullptr != enumListPath)
                {
                    pugi::xml_node enumListNode = enumListPath.node();
                    for (pugi::xml_node valueNode = enumListNode.first_child(); !valueNode.empty(); valueNode = valueNode.next_sibling())
                    {
                        std::wstring sDisplay = valueNode.attribute(L"Display").value();
                        std::wstring sText = valueNode.text().as_string();
                        mapValue[sText] = sDisplay;
                    }
                }

                break;
            }
        }
        return true;
    }

    bool UploadWindow::RemoveStandardNodesFromXML(const std::wstring& gacFile, const std::wstring& sParametersXml) const
    {
        pugi::xml_document xmlDoc;
        pugi::xml_parse_result result = xmlDoc.load(sParametersXml.c_str());
        DBG_WARN_AND_RETURN_UNLESS(pugi::status_ok == result.status, false, L"加载XML文件失败", L"GMEP", L"2024-01-30");

        DBG_WARN_AND_RETURN_UNLESS(nullptr != xmlDoc, false, L"xmlDoc为空", L"GMEP", L"2024-01-30");
        pugi::xpath_node paramsPath = xmlDoc.select_single_node(L"/Root/FamilyParameterDefinitions");
        if (nullptr == paramsPath)
            return true;

        pugi::xml_node paramsNode = paramsPath.node();
        if (nullptr == paramsNode)
            return true;

        // 删除definition相关段，如果有
        std::vector<std::wstring> removedParamNameVec;
        for (pugi::xml_node paramDefNode = paramsNode.first_child(); !paramDefNode.empty();)
        {
            pugi::xpath_node namePath = paramDefNode.select_single_node(L"Name");
            if (nullptr == namePath)
            {
                paramDefNode = paramDefNode.next_sibling();
                continue;
            }
            pugi::xml_node nameNode = namePath.node();
            if (nullptr == nameNode)
            {
                paramDefNode = paramDefNode.next_sibling();
                continue;
            }
            std::wstring sName = nameNode.text().as_string();
            if (sName.empty())
            {
                paramDefNode = paramDefNode.next_sibling();
                continue;
            }

            pugi::xpath_node standardTypePath = paramDefNode.select_single_node(L"StandardType");
            pugi::xpath_node standardCodePath = paramDefNode.select_single_node(L"StandardCode");
            std::wstring sStandardType = L"", sStandardCode = L"";
            if (nullptr != standardTypePath)
            {
                pugi::xml_node standardTypeNode = standardTypePath.node();
                sStandardType = standardTypeNode.text().as_string();
            }
            if (nullptr != standardCodePath)
            {
                pugi::xml_node standardCodeNode = standardCodePath.node();
                sStandardCode = standardCodeNode.text().as_string();
            }

            if ((sStandardType == L"StandardEssential" || sStandardType == L"StandardExtended") && !sStandardCode.empty())
            {
                pugi::xml_node tmpNode = paramDefNode.next_sibling();
                paramsNode.remove_child(paramDefNode);
                paramDefNode = tmpNode;

                removedParamNameVec.emplace_back(sName);
            }
            else
                paramDefNode = paramDefNode.next_sibling();
        }

        // 删除FamilyType相关name 的param
        if (!removedParamNameVec.empty())
        {
            pugi::xpath_node_set typeNodesPath = xmlDoc.select_nodes(L"/Root/FamilyType");
            if (typeNodesPath.empty())
                return true;
            for (auto typeNodePath = typeNodesPath.begin(); typeNodePath != typeNodesPath.end(); ++typeNodePath)
            {
                pugi::xml_node typeNode = typeNodePath->node();
                for (pugi::xml_node paramNode = typeNode.first_child(); !paramNode.empty(); )
                {
                    pugi::xpath_node namePath = paramNode.select_single_node(L"ParamName");
                    if (nullptr == namePath)
                    {
                        paramNode = paramNode.next_sibling();
                         continue;
                    }
                    pugi::xml_node nameNode = namePath.node();
                    if (nullptr == nameNode)
                    {
                        paramNode = paramNode.next_sibling();
                        continue;
                    }
                    std::wstring sName = nameNode.text().as_string();
                    if (sName.empty())
                    {
                        paramNode = paramNode.next_sibling();
                        continue;
                    }
                    if (std::find(removedParamNameVec.begin(), removedParamNameVec.end(), sName) != removedParamNameVec.end())
                    {
                        pugi::xml_node tmpNode = paramNode.next_sibling();
                        typeNode.remove_child(paramNode);
                        paramNode = tmpNode;                        
                    }
                    else
                        paramNode = paramNode.next_sibling();
                }
            }
           

            // 重新更新gac
            std::wstring strTempXMLFilePath = gcmp::FilePath::Combine(gcmp::FileSystem::GetTempDirPath(), L"FamilyParameters.xml");
            bool succ = xmlDoc.save_file(strTempXMLFilePath.c_str());
            if (succ)
            {
                succ = GacZipUtils::UpdateFamilyParameterXml(gacFile, strTempXMLFilePath);
                FileSystem::RemoveFile(strTempXMLFilePath);
            }
            DBG_WARN_AND_RETURN_UNLESS(succ, false, L"更新gac失败", L"GMEP", L"2024-01-30");
            return succ;
        }
        return true;
    }

    std::wstring UploadWindow::GetParameterDisplayType(const gcmp::UniIdentity& parameterTypeId) const
    {
        std::wstring sType = L"Invalid";
        if (parameterTypeId == PARAMETER_TYPE(Invalid))
        {
            sType = L"Invalid";
        }
        else if (parameterTypeId == PARAMETER_TYPE(None))
        {
            sType = L"NoDisplay";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Custom))
        {
            sType = L"Custom";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Length))
        {
            sType = L"Length";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Area))
        {
            sType = L"Area";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Volume))
        {
            sType = L"Volume";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Angle))
        {
            sType = L"Angle";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Slope))
        {
            sType = L"Slope";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Number))
        {
            sType = L"Number";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Text))
        {
            sType = L"Text";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Geometry))
        {
            sType = L"Geometry";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Density))
        {
            sType = L"Density";
        }
        else if (parameterTypeId == PARAMETER_TYPE(YesNo))
        {
            sType = L"YesOrNo";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Float))
        {
            sType = L"Float";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Material))
        {
            sType = L"Material";
        }
        else if (parameterTypeId == PARAMETER_TYPE(ValueList))
        {
            sType = L"ValueList";
        }
        else if (parameterTypeId == PARAMETER_TYPE(StandardCodeReference))
        {
            sType = L"StandardCodeReference";
        }
        else if (parameterTypeId == PARAMETER_TYPE(Color))
        {
            sType = L"Color";
        }
        else if (parameterTypeId == PARAMETER_TYPE(TextStyle))
        {
            sType = L"TextStyle";
        }
        return sType;
    }

    std::wstring UploadWindow::GetUnitType(const gcmp::UniIdentity& unitTypeId) const
    {
        std::wstring sUnitType = L"None";
        if (unitTypeId == UNIT(None))
        {
            sUnitType = L"None";
        }
        else if (unitTypeId == UNIT(Custom))
        {
            sUnitType = L"Custom";
        }
        else if (unitTypeId == UNIT(Number))
        {
            sUnitType = L"Number";
        }
        else if (unitTypeId == UNIT(Length))
        {
            sUnitType = L"Length";
        }
        else if (unitTypeId == UNIT(Angle))
        {
            sUnitType = L"Angle";
        }
        else if (unitTypeId == UNIT(Mass))
        {
            sUnitType = L"Mass";
        }
        else if (unitTypeId == UNIT(Time))
        {
            sUnitType = L"Time";
        }
        else if (unitTypeId == UNIT(ElectricCurrent))
        {
            sUnitType = L"ElectricCurrent";
        }
        else if (unitTypeId == UNIT(Temperature))
        {
            sUnitType = L"Temperature";
        }
        else if (unitTypeId == UNIT(LuminousIntensity))
        {
            sUnitType = L"LuminousIntensity";
        }
        else if (unitTypeId == UNIT(Area))
        {
            sUnitType = L"Area";
        }
        else if (unitTypeId == UNIT(Volume))
        {
            sUnitType = L"Volume";
        }
        else if (unitTypeId == UNIT(Density))
        {
            sUnitType = L"Density";
        }
        return sUnitType;
    }

    std::wstring UploadWindow::GetValueType(gcmp::ParameterStorageType eParameterStorageType) const
    {
        std::wstring sValueType = L"String";
        switch (eParameterStorageType)
        {
        case gcmp::ParameterStorageType::Bool:
            sValueType = L"Logic";
            break;

        case gcmp::ParameterStorageType::Int:
            sValueType = L"Number";
            break;

        case gcmp::ParameterStorageType::Double:
            sValueType = L"Number";
            break;

        case gcmp::ParameterStorageType::String:
            sValueType = L"String";
            break;
        }
        return sValueType;
    }

    std::wstring UploadWindow::GetParameterStorageType(gcmp::ParameterStorageType storageType) const
    {
        std::wstring sStorageType = L"Invalid";
        switch (storageType)
        {
        case ParameterStorageType::Invalid:
            sStorageType = L"Invalid";
            break;

        case ParameterStorageType::None:
            sStorageType = L"None";
            break;

        case ParameterStorageType::Custom:
            sStorageType = L"Custom";
            break;

        case ParameterStorageType::Bool:
            sStorageType = L"Bool";
            break;

        case ParameterStorageType::Int:
            sStorageType = L"Integer";
            break;

        case ParameterStorageType::Double:
            sStorageType = L"Double";
            break;

        case ParameterStorageType::String:
            sStorageType = L"String";
            break;

        case ParameterStorageType::Coordinates:
            sStorageType = L"Coordinates";
            break;

        case ParameterStorageType::ElementId:
            sStorageType = L"ElementId";
            break;

        case ParameterStorageType::BuildingStorey:
            sStorageType = L"BuildingStorey";
            break;

        case ParameterStorageType::Color:
            sStorageType = L"Color";
            break;

        case ParameterStorageType::StandardCodeReference:
            sStorageType = L"StandardCodeReference";
            break;

        case ParameterStorageType::Geometry:
            sStorageType = L"Geometry";
            break;

        case ParameterStorageType::Guid:
            sStorageType = L"Guid";
            break;

        case ParameterStorageType::Count:
            sStorageType = L"Count";
            break;
        }
        return sStorageType;
    }
}
